package fons.navigator.load.plugins;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.List;

import org.mozilla.universalchardet.UniversalDetector;

import au.com.bytecode.opencsv.CSVReader;

import com.google.common.collect.Lists;

import fons.navigator.load.plugin.DataReader;
import fons.navigator.load.plugin.Reader;
import fons.navigator.util.IOUtils;
import fons.navigator.util.settings.Configuration;

@Reader(description = "CSV-Datei lesen", shortDescription = "CSV (Datei)")
public class CsvDataReader implements DataReader {
	private static final String IMPORT_FILE = "Importieren aus";
	private static final String SEPARATOR = "Separator";
	private Configuration defaultConfiguration = createDefaultConfiguration();
	private Configuration configuration;

	private CSVReader csv;
	private boolean end;

	public CsvDataReader () {
		this.csv = null;
		this.end = false;
	}

	@Override
	public List<String> nextLine() throws Exception {
		final String filename = configuration.get(IMPORT_FILE, File.class).getCanonicalPath();
		if (csv == null) {
			FileInputStream fis = new FileInputStream(filename);			
			UniversalDetector detector = new UniversalDetector(null);
			byte buf[] = new byte[4096];
			int nread;
			while ((nread = fis.read(buf)) > 0 && !detector.isDone()) {
				detector.handleData(buf, 0, nread);
			}
			detector.dataEnd(); 
			String encoding = detector.getDetectedCharset();
			
			csv = new CSVReader(
					new InputStreamReader(IOUtils.asInputStream(filename), encoding),
					configuration.get(SEPARATOR, Character.class));
		}

		String[] line = csv.readNext();
		if (line == null || line.length == 0) {
			this.end = true;
			this.csv.close();

		} else {
			return Lists.newArrayList(line);
		}				

		return Lists.newArrayList();
	}

	@Override
	public boolean end() {
		return this.end;
	}

	@Override
	public void close() throws Exception {
		this.csv.close();
	}

	@Override
	public Configuration getConfiguration() {
		if (configuration == null) configuration = getDefaultConfiguration();
		return configuration;
	}

	@Override
	public void setDefaultConfiguration(Configuration configuration) {
		defaultConfiguration = configuration;
	}

	@Override
	public Configuration getDefaultConfiguration() {
		return defaultConfiguration.copy();
	}

	private Configuration createDefaultConfiguration() {
		Configuration config = new Configuration();
		config.addEmptySetting(File.class, IMPORT_FILE, "Import-Datei", true);
		config.addDefaultSetting(';', SEPARATOR, "Separator der CSV-Datei", true);
		return config;
	}
}
